Rack apps 看起來像一個方法或一個 proc
Rails 做更細部的設定,讓我們建立應用程式的時候,能用所有的 controller 跟 action
我們可以傳額外的參數給 controller 跟 action
# rainbow/lib/rainbow.rb
module Rulers
class Application
def call(env)
if env['PATH_INFO'] == '/favicon.ico'
return [404, {'Content-Type' => 'text/html'}, []]
end
klass, act = get_controller_and_action(env)
controller = klass.new(env)
text = controller.send(act)
r = controller.get_response
if r [r.status, r.headers, [r.body].flatten]
else [200, {'Content-Type' => 'text/html'}, [text]]
end
end
end
end
如果你想在 Rack app 中使用 controller 的 action
必須要用一個物件包起來,像 proc 一樣
我們來建立一個叫做 dispatch 的方法,並請他去使用 controller 的 action
塞額外的參數並把他們包在一個 proc 中
然後我們去呼叫 Rainbow 裡面的 action
# rainbow/lib/rainbow.rb
module Rulers
class Application
def call(env) # We’re updating this method
if env['PATH_INFO'] == '/favicon.ico'
return [404, {'Content-Type' => 'text/html'}, []]
end
# Don’t parse the route here,
# use a new method we'll write.
rack_app = get_rack_app(env)
rack_app.call(env)
end
end
end
# rainbow/lib/rainbow/controller.rb
module Rainbow
class Controller
include Rainbow::Model
def initialize(env)
@env = env
@routing_params = {} # Add this line!
end
def dispatch(action, routing_params = {})
@routing_params = routing_params
text = self.send(action)
r = get_response
if r
[r.status, r.headers, [r.body].flatten]
else
[200, {'Content-Type' => 'text/html'}, [text].flatten]
end
end
def self.action(act, rp = {})
proc { |e| self.new(e).dispatch(act, rp) }
end
# Change this too!
def params
request.params.merge @routing_params
end
end
end
現在,Rainbow 已經可以拿到 action
然後像 Rack 的 app 一樣使用 controller 的 action囉